// DBDeployer - The MySQL Sandbox
// Copyright © 2006-2020 Giuseppe Maxia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//go:build go1.16
// +build go1.16

package cookbook

import (
	_ "embed"
	"fmt"
	"os"

	"github.com/datacharmer/dbdeployer/common"
)

type RecipeTemplate struct {
	Description    string
	ScriptName     string
	Notes          string
	Contents       string
	RequiredFlavor string
	IsExecutable   bool
}

type RecipesCollection map[string]RecipeTemplate

const (
	CookbookInclude       = "cookbook_include.sh"
	CookbookPrerequisites = "prerequisites.sh"
)

//go:embed templates/include.gotxt
var recipeInclude string

//go:embed templates/single.gotxt
var singleTemplate string

//go:embed templates/custom-users.gotxt
var singleCustomUsersTemplate string

//go:embed templates/admin.gotxt
var adminPortTemplate string

//go:embed templates/skip-start-single.gotxt
var singleSkipStartTemplate string

//go:embed templates/single-reinstall.gotxt
var singleReinstallTemplate string

//go:embed templates/show.gotxt
var showSandboxes string

//go:embed templates/delete.gotxt
var deleteAll string

//go:embed templates/master-slave.gotxt
var masterSlaveDeployment string

//go:embed templates/skip-start-replication.gotxt
var replicationSkipStartTemplate string

//go:embed templates/custom-named-replication.gotxt
var customReplicationDeployment string

//go:embed templates/fan-in.gotxt
var fanInDeployment string

//go:embed templates/all-masters.gotxt
var allMastersDeployment string

//go:embed templates/group-multi.gotxt
var groupMultiPrimaryDeployment string

//go:embed templates/group-single.gotxt
var groupSinglePrimaryDeployment string

//go:embed templates/replication-restart.gotxt
var replicationRestart string

//go:embed templates/replication-operations.gotxt
var replicationOperations string

//go:embed templates/upgrade.gotxt
var upgradeTemplate string

//go:embed templates/tidb.gotxt
var tidbDeployment string

//go:embed templates/remote.gotxt
var remoteOperations string

//go:embed templates/ndb.gotxt
var ndbDeployment string

//go:embed templates/ndb.gotxt
var pxcDeployment string

//go:embed templates/prerequisites.gotxt
var prerequisites string

//go:embed templates/replication_between_groups.gotxt
var replicationBetweenGroups string

//go:embed templates/replication_between_master_slave.gotxt
var replicationBetweenMasterSlave string

//go:embed templates/replication_between_ndb.gotxt
var replicationBetweenNdb string

//go:embed templates/replication_multi_versions.gotxt
var replicationBetweenDiffVersions string

//go:embed templates/replication_between_single.gotxt
var replicationBetweenSingle string

//go:embed templates/circular_replication.gotxt
var circularReplication string

//go:embed templates/replication_single_group.gotxt
var replicationSingleGroup string

//go:embed templates/replication_group_single.gotxt
var replicationGroupSingle string

//go:embed templates/replication_group_master_slave.gotxt
var replicationGroupMasterSlave string

//go:embed templates/replication_master_slave_group.gotxt
var replicationMasterSlaveGroup string

/*
var newName string = `#!{{.ShellPath}}
{{.Copyright}}
# Generated by dbdeployer {{.AppVersion}} using template {{.TemplateName}} on {{.DateTime}}
cd $(dirname $0)
source cookbook_include.sh
[ -z "$version" ] && version=$(dbdeployer info version)
check_version $version
path_version=$(echo $version | tr '.' '_')
`
*/

var RecipesList = RecipesCollection{
	"include": RecipeTemplate{
		ScriptName:  CookbookInclude,
		Description: "common code for all recipes",
		Contents:    recipeInclude,
	},
	"single": RecipeTemplate{
		Description:  "Creation of a single sandbox",
		ScriptName:   "single-deployment.sh",
		Contents:     singleTemplate,
		IsExecutable: true,
	},
	"skip-start-single": RecipeTemplate{
		Description:  "Single sandbox deployed without starting the server",
		ScriptName:   "skip-start-single.sh",
		Contents:     singleSkipStartTemplate,
		IsExecutable: true,
	},
	"skip-start-replication": RecipeTemplate{
		Description:  "Replication sandbox deployed without starting the servers",
		ScriptName:   "skip-start-replication.sh",
		Contents:     replicationSkipStartTemplate,
		IsExecutable: true,
	},
	"custom-named-replication": RecipeTemplate{
		Description:  "Replication sandbox with custom names for directories and scripts",
		ScriptName:   "custom-named-replication.sh",
		Contents:     customReplicationDeployment,
		IsExecutable: true,
	},
	"custom-users": RecipeTemplate{
		Description:    "Single sandbox with custom users",
		ScriptName:     "single-custom-users.sh",
		Contents:       singleCustomUsersTemplate,
		RequiredFlavor: common.MySQLFlavor,
		IsExecutable:   true,
	},
	"admin": RecipeTemplate{
		Description:    "Single sandbox with admin address enabled",
		ScriptName:     "admin-single.sh",
		Contents:       adminPortTemplate,
		RequiredFlavor: common.MySQLFlavor,
		IsExecutable:   true,
	},
	"single-reinstall": RecipeTemplate{
		Description:  "Re-installs a single sandbox",
		ScriptName:   "single-reinstall.sh",
		Contents:     singleReinstallTemplate,
		IsExecutable: true,
	},
	"show": RecipeTemplate{
		Description:  "Show deployed sandboxes",
		ScriptName:   "show-sandboxes.sh",
		Contents:     showSandboxes,
		IsExecutable: true,
	},
	"delete": RecipeTemplate{
		Description:  "Delete all deployed sandboxes",
		ScriptName:   "delete-sandboxes.sh",
		Contents:     deleteAll,
		IsExecutable: true,
	},
	"master-slave": RecipeTemplate{
		Description:  "Creation of a master/slave replication sandbox",
		ScriptName:   "master-slave-deployment.sh",
		Contents:     masterSlaveDeployment,
		IsExecutable: true,
	},
	"fan-in": RecipeTemplate{
		Description:    "Creation of a fan-in (many masters, one slave) replication sandbox",
		ScriptName:     "fan-in-deployment.sh",
		Contents:       fanInDeployment,
		RequiredFlavor: common.MySQLFlavor,
		IsExecutable:   true,
	},
	"all-masters": RecipeTemplate{
		Description:    "Creation of an all-masters replication sandbox",
		ScriptName:     "all-masters-deployment.sh",
		Contents:       allMastersDeployment,
		RequiredFlavor: common.MySQLFlavor,
		IsExecutable:   true,
	},
	"group-multi": RecipeTemplate{
		Description:    "Creation of a multi-primary group replication sandbox",
		ScriptName:     "group-multi-primary-deployment.sh",
		Contents:       groupMultiPrimaryDeployment,
		RequiredFlavor: common.MySQLFlavor,
		IsExecutable:   true,
	},
	"group-single": RecipeTemplate{
		Description:    "Creation of a single-primary group replication sandbox",
		ScriptName:     "group-single-primary-deployment.sh",
		Contents:       groupSinglePrimaryDeployment,
		RequiredFlavor: common.MySQLFlavor,
		IsExecutable:   true,
	},
	"replication-restart": RecipeTemplate{
		Description:  "Show how to restart sandboxes with custom options",
		ScriptName:   "repl-operations-restart.sh",
		Contents:     replicationRestart,
		IsExecutable: true,
	},
	"replication-operations": RecipeTemplate{
		Description:  "Show how to run operations in a replication sandbox",
		ScriptName:   "repl-operations.sh",
		Contents:     replicationOperations,
		IsExecutable: true,
	},
	"upgrade": RecipeTemplate{
		Description:    "Shows a complete upgrade example from 5.5 to 8.0",
		ScriptName:     "upgrade.sh",
		Contents:       upgradeTemplate,
		RequiredFlavor: common.MySQLFlavor,
		IsExecutable:   true,
	},
	"tidb": RecipeTemplate{
		Description:    "Shows deployment and some operations with TiDB",
		ScriptName:     "tidb-deployment.sh",
		Contents:       tidbDeployment,
		RequiredFlavor: common.TiDbFlavor,
		IsExecutable:   true,
	},
	"ndb": RecipeTemplate{
		Description:    "Shows deployment with ndb",
		ScriptName:     "ndb-deployment.sh",
		Contents:       ndbDeployment,
		RequiredFlavor: common.NdbFlavor,
		IsExecutable:   true,
	},
	"pxc": RecipeTemplate{
		Description:    "Shows deployment with pxc",
		ScriptName:     "pxc-deployment.sh",
		Contents:       pxcDeployment,
		RequiredFlavor: common.PxcFlavor,
		IsExecutable:   true,
	},
	"remote": RecipeTemplate{
		Description:  "Shows how to get a remote MySQL tarball",
		ScriptName:   "remote.sh",
		Contents:     remoteOperations,
		IsExecutable: true,
	},
	"prerequisites": RecipeTemplate{
		Description:  "Shows dbdeployer prerequisites and how to make them",
		ScriptName:   CookbookPrerequisites,
		Contents:     prerequisites,
		IsExecutable: true,
	},
	"replication_between_groups": RecipeTemplate{
		Description:    "Shows how to run replication between two group replications",
		ScriptName:     "replication-between-groups.sh",
		Contents:       replicationBetweenGroups,
		RequiredFlavor: common.MySQLFlavor,
		IsExecutable:   true,
	},
	"replication_between_master_slave": RecipeTemplate{
		Description:  "Shows how to run replication between two master/slave replications",
		ScriptName:   "replication-between-master-slave.sh",
		Contents:     replicationBetweenMasterSlave,
		IsExecutable: true,
	},
	"replication_between_ndb": RecipeTemplate{
		Description:    "Shows how to run replication between two NDB clusters",
		ScriptName:     "replication-between-ndb.sh",
		Contents:       replicationBetweenNdb,
		RequiredFlavor: common.NdbFlavor,
		IsExecutable:   true,
	},
	"replication_multi_versions": RecipeTemplate{
		Description:  "Shows how to run replication between different MySQL versions",
		ScriptName:   "replication-multi-versions.sh",
		Contents:     replicationBetweenDiffVersions,
		IsExecutable: true,
	},
	"replication_group_single": RecipeTemplate{
		Description:    "Shows how to run replication between a group replication and a single sandbox",
		ScriptName:     "replication-group-single.sh",
		Contents:       replicationGroupSingle,
		RequiredFlavor: common.MySQLFlavor,
		IsExecutable:   true,
	},
	"replication_single_group": RecipeTemplate{
		Description:    "Shows how to run replication between a single sandbox an group replication",
		ScriptName:     "replication-single-group.sh",
		Contents:       replicationSingleGroup,
		RequiredFlavor: common.MySQLFlavor,
		IsExecutable:   true,
	},
	"replication_between_single": RecipeTemplate{
		Description:  "Shows how to run replication between two single sandboxes",
		ScriptName:   "replication-between-single.sh",
		Contents:     replicationBetweenSingle,
		IsExecutable: true,
	},
	"circular_replication": RecipeTemplate{
		Description:  "Shows how to run replication between nodes of a multiple deployment",
		ScriptName:   "circular-replication.sh",
		Contents:     circularReplication,
		IsExecutable: true,
	},
	"replication_group_master_slave": RecipeTemplate{
		Description:    "Shows how to run replication between a group replication and master/slave replication",
		ScriptName:     "replication-group-master-slave.sh",
		Contents:       replicationGroupMasterSlave,
		RequiredFlavor: common.MySQLFlavor,
		IsExecutable:   true,
	},
	"replication_master_slave_group": RecipeTemplate{
		Description:    "Shows how to run replication between master/slave replication and group replication",
		ScriptName:     "replication-master-slave-group.sh",
		Contents:       replicationMasterSlaveGroup,
		RequiredFlavor: common.MySQLFlavor,
		IsExecutable:   true,
	},
}

func init() {
	var seen = make(map[string]bool)
	for name, recipe := range RecipesList {
		_, found := seen[recipe.ScriptName]
		if found {
			// script name already exists:
			fmt.Printf("Duplicate script name %s found in %s\n", recipe.ScriptName, name)
			os.Exit(1)

		}
	}
}
